﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Barcode
{
    /// <summary>
    /// Interaktionslogik für Code128.xaml
    /// </summary>
    public partial class Code128 : UserControl
    {
        public Code128()
        {
            InitializeComponent();
            Initialize();
        }

        public static readonly DependencyProperty BarcodeProperty = DependencyProperty.Register(
     "Barcode",
     typeof(string),
     typeof(Code128),
     new FrameworkPropertyMetadata(
         "",
         FrameworkPropertyMetadataOptions.AffectsRender |
         FrameworkPropertyMetadataOptions.AffectsParentMeasure,
         new PropertyChangedCallback(onBarcodeChanged)));

        public static void onBarcodeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((Code128)d).Barcode = (string)e.NewValue;
        }

        public string Barcode
        {
            get { return (string)GetValue(BarcodeProperty); }
            set { SetValue(BarcodeProperty, value); }
        }

        BarChar[] bardefs;
        public double _xdim = 0.5;
        public double _height = 1;

        string _prefix = "XX";
        double xdim = 1;

        BarChar bc(int id, string bar)
        {
            return new BarChar(id, bar);
        }

        public void Initialize()
        {

            bardefs = new BarChar[] {
             
                bc(0,"212222"),
                bc(1,"222122"),
                bc(2,"222221"),
                bc(3,"121223"),
                bc(4,"121322"),
                bc(5,"131222"),
                bc(6,"122213"),
                bc(7,"122312"),
                bc(8,"132212"),
                bc(9,"221213"),
                bc(10,"221312"),
                bc(11,"231212"),
                bc(12,"112232"),
                bc(13,"122132"),
                bc(14,"122231"),
                bc(15,"113222"),
                bc(16,"123122"),
                bc(17,"123221"),
                bc(18,"223211"),
                bc(19,"221132"),
                bc(20,"221231"),
                bc(21,"213212"),
                bc(22,"223112"),
                bc(23,"312131"),
                bc(24,"311222"),
                bc(25,"321122"),
                bc(26,"321221"),
                bc(27,"312212"),
                bc(28,"322112"),
                bc(29,"322211"),
                bc(30,"212123"),
                bc(31,"212321"),
                bc(32,"232121"),
                bc(33,"111323"),
                bc(34,"131123"),
                bc(35,"131321"),
                bc(36,"112313"),
                bc(37,"132113"),
                bc(38,"132311"),
                bc(39,"211313"),
                bc(40,"231113"),
                bc(41,"231311"),
                bc(42,"112133"),
                bc(43,"112331"),
                bc(44,"132131"),
                bc(45,"113123"),
                bc(46,"113321"),
                bc(47,"133121"),
                bc(48,"313121"),
                bc(49,"211331"),
                bc(50,"231131"),
                bc(51,"213113"),
                bc(52,"213311"),
                bc(53,"213131"),
                bc(54,"311123"),
                bc(55,"311321"),
                bc(56,"331121"),
                bc(57,"312113"),
                bc(58,"312311"),
                bc(59,"332111"),
                bc(60,"314111"),
                bc(61,"221411"),
                bc(62,"431111"),
                bc(63,"111224"),
                bc(64,"111422"),
                bc(65,"121124"),
                bc(66,"121421"),
                bc(67,"141122"),
                bc(68,"141221"),
                bc(69,"112214"),
                bc(70,"112412"),
                bc(71,"122114"),
                bc(72,"122411"),
                bc(73,"142112"),
                bc(74,"142211"),
                bc(75,"241211"),
                bc(76,"221114"),
                bc(77,"413111"),
                bc(78,"241112"),
                bc(79,"134111"),
                bc(80,"111242"),
                bc(81,"121142"),
                bc(82,"121241"),
                bc(83,"114212"),
                bc(84,"124112"),
                bc(85,"124211"),
                bc(86,"411212"),
                bc(87,"421112"),
                bc(88,"421211"),
                bc(89,"212141"),
                bc(90,"214121"),
                bc(91,"412121"),
                bc(92,"111143"),
                bc(93,"111341"),
                bc(94,"131141"),
                bc(95,"114113"),
                bc(96,"114311"),
                bc(97,"411113"),
                bc(98,"411311"),
                bc(99,"113141"),
                bc(100,"114131"),
                bc(101,"311141"),
                bc(102,"411131"),
                bc(103,"211412"),
                bc(104,"211214"),
                bc(105,"211232"),
                bc(106,"2331112")
            };
        }

        public string Prefix
        {
            set { _prefix = value; }
            get { return _prefix; }
        }

        string Bars(List<int> chars)
        {
            StringBuilder sb = new StringBuilder();
            foreach (int i in chars)
                sb.Append(bardefs[i].bars);
            return sb.ToString();
        }

        List<int> BarData(string bar)
        {
            string s = bar;

            string chars = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwxyz{|}~";
            int n = 0;

            if (s.Length % 2 != 0)
                s = "0" + s;

            int chk;
            int p = 0;

            List<int> t = new List<int>();
            t.Add(104);
            chk = 104;
            n += 11;

            for (int i = 0; i < _prefix.Length; i++)
            {
                int ix = chars.IndexOf(_prefix[i]);
                if (ix >= 0)
                {
                    t.Add(ix);
                    p++;
                    chk += p * ix;
                    n += 11;
                }
            }

            t.Add(99);
            p++;
            chk += p * 99;
            n += 11;

            for (int i = 0; i < s.Length; i += 2)
            {
                string a = s.Substring(i, 2);

                int v = int.Parse(a);
                t.Add(v);
                p++;
                chk += p * v;
                n += 11;
            }

            chk = chk - 103 * (chk / 103);
            t.Add(chk);
            n += 11;
            t.Add(106);
            n += 13;

            xdim = Width / n;

            return t;
        }

        protected override void OnRender(DrawingContext dc)
        {
            double x = 0;
            double y = 0;
            double w = 1;

            string bar = Barcode;
            if (bar == null)
                return;

            List<int> data = BarData(bar);

            Brush b = new SolidColorBrush(Color.FromRgb(0, 0, 0));
            Pen p = new Pen(b, 0.0);

            bool Black = true;
            foreach (int c in data)
            {
                string t = bardefs[c].bars;


                for (int i = 0; i < t.Length; i++)
                {
                    int n = 0;
                    switch (t[i])
                    {
                        case '1': n = 1; break;
                        case '2': n = 2; break;
                        case '3': n = 3; break;
                        case '4': n = 4; break;
                    }
                    if (n > 0)
                    {
                        w = xdim * n;
                        if (Black)
                        {
                            Rect r = new Rect(x, y, w, Height);
                            dc.DrawRectangle(b, p, r);
                        }
                        x += w;
                        Black = !Black;
                    }
                }
            }
        }

    }

    class BarChar
    {
        public int id;
        public string bars;

        public BarChar(int i, string b)
        {
            id = i;
            bars = b;
        }
    }
}
